home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Peter Lewis / PNL Libraries / ShowIconFamily.p < prev    next >
Encoding:
Text File  |  1994-06-18  |  10.1 KB  |  357 lines  |  [TEXT/PJMM]

  1. unit ShowIconFamily;
  2. (*}
  3. {# Pascal conversion : Quinn}
  4. {# Station : Eriodon}
  5. {# Date : Tuesday, 11 February 1992}
  6. {*)
  7. interface
  8.  
  9. (*}
  10. {    ShowIconFamily.c}
  11. {    }
  12. {    ShowINIT compatible routine that shows 'ICN#' and 'iclx' flavor icons.}
  13. {    For use by all INITs in System 7 and beyond.}
  14. {    }
  15. {    by Patrick C. Beard.}
  16. {    }
  17. {    Instructions for use:}
  18. {    }
  19. {        • Create a family of icons with ResEdit 2.1 or later.  This will include}
  20. {         'ICN#', 'icl4', & 'icl8' icons.}
  21. {        • Use SetUpA4 to set up Think C globals.}
  22. {        • Call ShowIconFamily() with the resource id of the family that you used.}
  23. {    }
  24. {    Enhancements:}
  25. {        }
  26. {        • Uses 'iclx' & 'ICN#' icons from the Finder's "icon family" in System 7.}
  27. {        • Generates a position for icons that is guaranteed to be on screen, while}
  28. {          remaining compatible with previous releases of ShowInit.}
  29. {}
  30. {    This code is completely public domain.  Let's hope this becomes a new standard.}
  31. {    }
  32. {    This code is derived from the original ShowInit by Paul Mercer, Darin Adler,}
  33. {    Paul Snively, and Steve Capps.}
  34. {    }
  35. {    Special thanks to Ben Haller, Rob Vaterlaus for valuable suggestions and help.}
  36. {    Also, thanks, and in memory of, Mouse Herrel, for bug detection.}
  37. {}
  38. {    Patrick C. Beard}
  39. {    1/8/92}
  40. {}
  41. {    ------------------------------------------------------------------------------}
  42. {    Modification History:}
  43. {    }
  44. {    1/8/92 - This version is for THINK C 5.0 or better. Uses MPW-style includes. PB}
  45. {    8/2/91 - Wasn't calling ClosePort after using the port.  Bad thing.  Fixed.  PB}
  46. {    11 Feb 1992 - Converted to Pascal (MPW and Think (hopefully))}
  47. {    17 Feb 1992 - Changed default_delta_x to -1 to act like ShowInit}
  48. {    ------------------------------------------------------------------------------}
  49. {*)
  50.  
  51.     const
  52.         default_delta_x = -1;
  53.  
  54.     procedure SHOWICON (id: integer; delta_x: integer);
  55.  
  56. implementation
  57.  
  58. {$ifc undefined THINK_Pascal}
  59.     uses
  60.         Types, OSUtils, QuickDraw, Resources, Memory;
  61. {$endc}
  62.  
  63.     type
  64.         qdGlobals = record
  65.                 private: array[0..75] of signedByte;
  66.                 randSeed: longint;
  67.                 screenBits: BitMap;
  68.                 arrow: Cursor;
  69.                 dkGray: Pattern;
  70.                 ltGray: Pattern;
  71.                 gray: Pattern;
  72.                 black: Pattern;
  73.                 white: Pattern;
  74.                 thePort: GrafPtr;
  75.                 theend: longint;
  76.             end;
  77.  
  78.     procedure SHOWICON (id: integer; delta_x: integer);
  79.         var
  80.             theGrafPort: GrafPtr;
  81.             theDepth: integer;
  82.  
  83.         procedure GetIconRect (var iconRect: Rect);
  84.             (*}
  85. {                GetIconRect() generates an appropriate rectangle to display the}
  86. {                next INIT's icon in.  It is also responsible for updating the horizontal}
  87. {                position in low memory.  This is a departure from the original ShowInit code,}
  88. {                which updates low memory AFTER displaying the icon.  This code won't generate}
  89. {                an icon position until it is certain that the icon can be loaded, so the}
  90. {                same behaviour occurs.}
  91. {                }
  92. {                This routine also generates a rectangle which is guaranteed to be onscreen.  It}
  93. {                does this by taking the horizontal offset modulo the screen width to generate}
  94. {                the horizontal position of the icon, and the offset divided by the screen}
  95. {                width to generate the proper row.}
  96. {            *)
  97.  
  98.             function CalcCheckSum (i: integer): integer;
  99.                 (*}
  100. {                    ShowInit's information is nestled at the tail end of CurApName.}
  101. {                    It consists of a short which encodes the next horizontal offset,}
  102. {                    and another short which is that value checksummed with the function below.}
  103. {                *)
  104.                 const
  105.                     check_sum_const = $1021;
  106.                 var
  107.                     l: longint;
  108.             begin
  109.                 (* 16 bit rol is not pleasant in Pascal )-: *)
  110.                 l := brotl(l, 1);
  111.                 l := band(l, $FFFE);
  112.                 if btst(i, 15) then begin
  113.                     l := bor(l, 1);
  114.                 end; (* if *)
  115.                 CalcCheckSum := bxor(l, check_sum_const);
  116.             end; (* CalcCheckSum *)
  117.  
  118.             const
  119.                 CurApName = $910;
  120.                 offset_addr = CurApName + 32 - 4;                (* both pointers to integers *)
  121.                 checksum_addr = CurApName + 32 - 2;
  122.  
  123.                 initial_x_position = 8;        (* initial horizontal offset. *)
  124.                 y_offset = 40;                        (* constant from bottom to place the icon. *)
  125.             type
  126.                 intPtr = ^integer;
  127.             var
  128.                 screenWidth: integer;
  129.                 offset: integer;
  130.                 checksum: integer;
  131.         begin
  132.             screenWidth := theGrafPort^.portRect.right - theGrafPort^.portRect.left;
  133.             offset := intPtr(offset_addr)^;
  134.             checksum := intPtr(checksum_addr)^;
  135.  
  136.             (* if we are the first INIT to run we need to initialize the horizontal value. *)
  137.             if CalcCheckSum(offset) <> checksum then begin
  138.                 offset := initial_x_position;
  139.             end; (* if *)
  140.  
  141.             iconRect.left := offset mod screenWidth;
  142.             iconRect.top := theGrafPort^.portRect.bottom - y_offset * (offset div screenWidth + 1);
  143.             iconRect.right := iconRect.left + 32;
  144.             iconRect.bottom := iconRect.top + 32;
  145.  
  146.             (* advance the position for the next icon. *)
  147.             offset := offset + delta_x;
  148.  
  149.             intPtr(offset_addr)^ := offset;
  150.             intPtr(checksum_addr)^ := CalcCheckSum(offset);
  151.         end; (* GetIconRect *)
  152.  
  153.         procedure DrawBWIcon (iconid: integer);
  154.             (* DrawBWIcon draws the 'ICN#' member of the icon family. *)
  155.             var
  156.                 icon: Handle;
  157.                 iconRect: Rect;
  158.                 source, destination: BitMap;
  159.         begin
  160.             icon := Get1Resource('ICN#', iconid);
  161.             if icon = nil then
  162.                 exit(DrawBWIcon);        (* yuk C conversion *)
  163.             HLock(icon);
  164.  
  165.             GetIconRect(iconRect);
  166.  
  167.             (* prepare the source and destination bitmaps. *)
  168.             source.baseAddr := Ptr(longint(icon^) + 128);                (* mask address. *)
  169.             source.rowBytes := 4;
  170.             SetRect(source.bounds, 0, 0, 32, 32);
  171.             destination := theGrafPort^.portBits;
  172.  
  173.             (* transfer the mask. *)
  174.             CopyBits(source, destination, source.bounds, iconREct, srcBic, nil);
  175.  
  176.             (* and the icon. *)
  177.             source.baseAddr := icon^;
  178.             CopyBits(source, destination, source.bounds, iconRect, srcOr, nil);
  179.  
  180.             ReleaseResource(icon);
  181.         end; (* DrawBWIcon *)
  182.  
  183.         procedure DrawColorIcon (iconid: integer);
  184.         (* DrawColorIcon draws the appropriate icon for the current screen depth. *)
  185.  
  186.             function ChooseIcon (iconid: integer; var suggestedDepth: integer): Handle;
  187.                 (*}
  188. {                    ChooseIcon() chooses the optimal icon for the current screen depth.}
  189. {                    }
  190. {                    Priorities for choosing icons:}
  191. {                        1. match the bit depth to the icon.}
  192. {                        2. use alternate bit depth version if available.}
  193. {                        3. draw the black & white version.}
  194. {                *)
  195.                 var
  196.                     icon: Handle;
  197.             begin
  198.                 icon := nil;
  199.                 if suggestedDepth = 4 then begin
  200.                     icon := Get1Resource('icl4', iconid);
  201.                     if icon = nil then begin
  202.                         icon := Get1Resource('icl8', iconid);
  203.                         if icon <> nil then begin
  204.                             suggestedDepth := 8;
  205.                         end; (* if *)
  206.                     end; (* if *)
  207.                 end
  208.                 else begin
  209.                     suggestedDepth := 8;
  210.                     icon := Get1Resource('icl8', iconid);
  211.                     if icon = nil then begin
  212.                         icon := Get1Resource('icl4', iconid);
  213.                         if icon <> nil then begin
  214.                             suggestedDepth := 4;
  215.                         end; (* if *)
  216.                     end; (* if *)
  217.                 end; (* if *)
  218.                 ChooseIcon := icon;
  219.             end; (* ChooseIcon *)
  220.  
  221.             var
  222.                 depthToUse: integer;
  223.                 mask, icon: Handle;
  224.                 clut: CTabHandle;
  225.                 source: PixMapHandle;
  226.                 maskBits: BitMap;
  227.                 rowBytes: longint;
  228.                 iconRect, bounds: Rect;
  229.         begin
  230.             (* by default we will be using the actual depth of the screen. *)
  231.             depthToUse := theDepth;
  232.             icon := ChooseIcon(iconid, depthToUse);
  233.  
  234.             if icon = nil then begin
  235.                 DrawBWIcon(iconid);
  236.                 exit(DrawColorIcon);
  237.             end; (* if *)
  238.  
  239.             HLock(icon);
  240.  
  241.             (* get the black & white icon to get the mask drawn. *)
  242.             mask := Get1Resource('ICN#', iconid);
  243.             if mask = nil then
  244.                 exit(DrawColorIcon);        (* C error checking (-: *)
  245.  
  246.             HLock(mask);
  247.  
  248.             (* get the correct color lookup table. *)
  249.             clut := GetCTable(depthToUse);
  250.             if clut = nil then
  251.                 exit(DrawColorIcon);        (* C error checking (-: *)
  252.  
  253.             (* create a pixmap to stick the icon bits into for screen blitting. *)
  254.             source := NewPixMap;
  255.             if source = nil then begin
  256.                 DisposCTable(clut);
  257.                 exit(DrawColorIcon);
  258.             end; (* if *)
  259.  
  260.             (* set up the source pixmap with the appropriate bounds, depth, and clut. *)
  261.             bounds.top := 0;
  262.             bounds.left := 0;
  263.             bounds.bottom := 32;
  264.             bounds.right := 32;
  265.             rowBytes := (depthToUse * 32 + 15) div 16 * 2;
  266.             source^^.baseAddr := icon^;
  267.             source^^.rowBytes := bor(LoWrd(rowBytes), $8000);
  268.             source^^.bounds := bounds;
  269.             source^^.pixelType := 0;                        (* chunky model. *)
  270.             source^^.pixelSize := depthToUse;
  271.             source^^.cmpCount := 1;                            (* if in 32 bit mode this will be 3, so must change. *)
  272.             source^^.cmpSize := depthToUse;
  273.             DisposCTable(source^^.pmTable);            (* dispose of default, uninitialized table. *)
  274.             source^^.pmTable := clut;
  275.  
  276.             (* get position to draw icon in. *)
  277.             GetIconRect(iconRect);
  278.  
  279.             (* prepare the mask bitmap. *)
  280.             maskBits.baseAddr := Ptr(longint(mask^) + 128);
  281.             maskBits.rowBytes := 4;
  282.             maskBits.bounds := bounds;
  283.  
  284.             (* punch out the mask *)
  285.             CopyBits(maskBits, theGrafPort^.portBits, bounds, iconRect, srcBic, nil);
  286.  
  287.             (* draw the actual color icon. *)
  288.             HLock(Handle(source));
  289.             CopyBits(BitMapPtr(source^)^, theGrafPort^.portBits, bounds, iconRect, srcOr, nil);
  290.  
  291.             (* release everything we've allocated. *)
  292.             source^^.baseAddr := nil;
  293.             DisposPixMap(source);
  294.  
  295.             (* release the icon and mask. *)
  296.             ReleaseResource(icon);
  297.             ReleaseResource(mask);
  298.         end; (* DrawColorIcon *)
  299.  
  300.         const
  301.             actual_default_delta_x = 40;
  302.         var
  303.             oldA5: longint;
  304.             qd: qdGlobals;
  305.             environment: SysEnvRec;
  306.             colorPort: boolean;
  307.             gp: CGrafPort;
  308.             junklong: longint;
  309.             junk: OSErr;
  310.     begin
  311.         oldA5 := SetA5(longint(@qd.theend));
  312.         InitGraf(@qd.thePort);
  313.  
  314.         if delta_x = default_delta_x then begin
  315.             delta_x := actual_default_delta_x;
  316.         end; (* if *)
  317.  
  318.         (* find out what kind of machine this is *)
  319.         junk := SysEnvirons(curSysEnvVers, environment);
  320.         if environment.hasColorQD then begin
  321.             theDepth := GetMainDevice^^.gdPMap^^.pixelSize;
  322.             if theDepth < 4 then begin
  323.                 theDepth := 1;
  324.             end; (* if *)
  325.         end
  326.         else begin
  327.             theDepth := 1;
  328.         end; (* if *)
  329.  
  330.         (* see what type of port to open. *)
  331.         colorPort := (theDepth >= 4);
  332.         theGrafPort := @gp;
  333.         if colorPort then begin
  334.             OpenCPort(CGrafPtr(theGrafPort));
  335.         end
  336.         else begin
  337.             OpenPort(theGrafPort);
  338.         end; (* if *)
  339.  
  340.         if theDepth = 1 then begin
  341.             DrawBWIcon(id);
  342.         end
  343.         else begin
  344.             DrawColorIcon(id);
  345.         end; (* if *)
  346.  
  347.         if colorPort then begin
  348.             CloseCPort(@gp);
  349.         end
  350.         else begin
  351.             ClosePort(@gp);
  352.         end; (* if *)
  353.  
  354.         junklong := SetA5(oldA5);
  355.     end; (* ShowIcon *)
  356.  
  357. end. (* ShowIconFamily *)